/*
 * This file is part of the Try! Engine project.
 *
 * Copyright 2010-2011 Emanuele Bertoldi. All rights reserved.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the modified BSD License along with this
 * program. If not, see <http://www.opensource.org/licenses/bsd-license.php>
 */

#include "logic.h"
#include <mouselistener.h>
#include <physicsmanager.h>
#include <rigidbody.h>
#include <scenetransformable.h>
#include <cameranode.h>
#include <application.h>

Logic::Logic()
{
}

Logic::~Logic()
{
}

void Logic::onMessage(const Try::Message& msg, Try::Object* sender, Try::Property* property)
{
    BaseAppLogic::onMessage(msg, sender, property);

    if (BaseAppLogic::isApplication(sender))
    {
        if (!property && msg.is(Application::Msg::updateRequest))
            physics->simulateOneStep(msg.param<double>());

        else if (property && msg.is(MouseListener::Msg::mousePressed))
        {
            int button = msg.param<int>();

            switch (button)
            {
                case MouseListener::MOUSE_BUTTON_LEFT:
                {
                    MouseListener* mouse = sender->property<MouseListener>(MouseListener::name);
                    float nx = mouse->normX();
                    float ny = mouse->normY();

                    // FIXME: hard-coded.
                    Application* app = static_cast<Application*>(this->object(0));

                    if (app)
                    {
                        SceneNode* picked = app->window()->activeCamera()->pickNode(nx, ny);

                        if (picked)
                        {
                            // FIXME: hard-coded.
                            Object* ball = this->object(1);
                            SceneTransformable* st = ball->property<SceneTransformable>();
                            if (st  && (st->sceneNode() == picked))
                            {
                                RigidBody* rb = ball->property<RigidBody>(RigidBody::name);
                                if (rb)
                                {
                                    btRigidBody* body = rb->body();
                                    body->activate(true);
                                    body->applyCentralImpulse(btVector3(0, 5, 0));
                                }
                            }
                        }
                    }
                }
                break;

                default:
                break;
            }
        }
    }
}
